/*

Miranda IM: the free IM client for Microsoft* Windows*

Copyright 2000-2007 Miranda ICQ/IM project, 
all portions of this codebase are copyrighted to the people 
listed in contributors.txt.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or ( at your option ) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "commonheaders.h"
#include "ExtraServices.h"

namespace NServices 
{
	namespace ViewHomepage 
	{

		static HANDLE nhMenuItem		= NULL;
		static HANDLE nhExtraIcon		= INVALID_HANDLE_VALUE;

		/**
		 * This function reads the homepage address of the contact.
		 *
		 * @param		hContact	- handle to contact to read email from
		 *
		 * @retval	URL to contacts homepage
		 * @retval	NULL if contact provides no homepage
		 **/
		static LPSTR Get( HANDLE hContact )
		{
			// ignore owner
			if( hContact != NULL ) 
			{
				LPCSTR szProto = DB::Contact::Proto( hContact );
				
				if( szProto != NULL ) 
				{
					LPCSTR	e[2] = { SET_CONTACT_HOMEPAGE, SET_CONTACT_COMPANY_HOMEPAGE };

					INT i;
					DBVARIANT dbv;

					for( i = 0; i < 2; i++ )
					{
						if( !DB::Setting::GetAStringEx( hContact, USERINFO, szProto, e[i], &dbv ) )
						{
							if( mir_strlen( dbv.pszVal ) > 2 )
							{
								return dbv.pszVal;
							}
							DB::Variant::Free( &dbv );
						}
					}
				}
			}
			return NULL;
		}

		/**
		 * Service function that opens the default browser and displays the homepage.
		 *
		 * @param	wParam	- handle to contact to send an email to
		 * @param	lParam	- not used
		 *
		 * @retval	0 if email was sent
		 * @retval	1 if no email can be sent
		 **/
		static INT MenuCommand( WPARAM wParam, LPARAM lParam )
		{
			LPSTR szUrl = Get( ( HANDLE )wParam );

			if( szUrl ) 
			{
				CallService( MS_UTILS_OPENURL, 1, ( LPARAM )szUrl );
				mir_free( szUrl );
			}
			else
			{
				MessageBox( ( HWND )lParam, 
					TranslateT( "User has no valid homepage" ),
					TranslateT( "View Homepage" ), MB_OK );
			}
			return 0;
		}

		/***********************************************************************************************************
		 * Event Handler functions
		 ***********************************************************************************************************/

		static INT OnCListRebuildIcons( WPARAM wParam, LPARAM lParam )
		{
			nhExtraIcon = ( HANDLE )CallService( MS_CLIST_EXTRA_ADD_ICON, ( WPARAM )NIcoLib::GetIcon( ICO_BTN_GOTO ), 0 );
			return 0;
		}

		/**
		 * Notification handler for clist extra icons to be applied for a contact.
		 *
		 * @param wParam	- handle to the contact whose extra icon is to apply
		 * @param	lParam	- not used
		 **/
		static INT OnCListApplyIcons( WPARAM wParam, LPARAM lParam )
		{
			IconExtraColumn iec;
			LPSTR szUrl;

			iec.cbSize = sizeof( IconExtraColumn );
			// to support the ugly shitfuckin' clist_nicer++
			iec.ColumnType = myGlobals.IsCListNicer ? 1 : EXTRA_ICON_WEB;
			
			szUrl = Get( ( HANDLE )wParam );
			if( szUrl ) 
			{
				iec.hImage = nhExtraIcon;
				mir_free( szUrl );
			}
			else
			{
				iec.hImage = INVALID_HANDLE_VALUE;
			}

			CallService( MS_CLIST_EXTRA_SET_ICON, wParam, ( LPARAM )&iec );
			return 0;
		}

		/**
		 * Notification handler for changed contact settings
		 *
		 * @param	wParam	-	( HANDLE )hContact
		 * @param	lParam	-	( DBCONTACTWRITESETTING* )pdbcws
		 **/
		static INT OnContactSettingChanged( WPARAM wParam, LPARAM lParam )
		{
			if( wParam )
			{
				DBCONTACTWRITESETTING* pdbcws = ( DBCONTACTWRITESETTING* )lParam;
				
				if( pdbcws )
				{
					if( 
							!mir_strncmp( pdbcws->szSetting, SET_CONTACT_HOMEPAGE, 8 ) ||
							!mir_strncmp( pdbcws->szSetting, SET_CONTACT_COMPANY_HOMEPAGE, 15 )				
						) 
					{
						OnCListApplyIcons( wParam, 0 );
					}
				}
			}
			return 0;
		}

		/**
		 * This function decides whether to show menuitem for sending emails or not.
		 *
		 * @param		wParam	- handle to contact to send an email to
		 * @param		lParam	- not used
		 *
		 * @return	always 0
		 **/
		static INT OnPreBuildMenu( WPARAM wParam, LPARAM lParam )
		{
			CLISTMENUITEM mi;
			LPSTR val;
			
			ZeroMemory( &mi, sizeof( mi ) );
			mi.cbSize = sizeof( mi );
			mi.flags = CMIM_FLAGS;

			val = Get( ( HANDLE )wParam );
			if( val ) 
			{
				mir_free( val );
			}
			else 
			{
				mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
			}
			CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )nhMenuItem, ( LPARAM )&mi );
			return 0;
		}

		/***********************************************************************************************************
		 * public Module Interface functions
		 ***********************************************************************************************************/

		/**
		 * name:	RebuildMenu
		 * desc:	enable or disable menuitem
		 * params:	not used
		 * return:	nothing
		 **/
		VOID RebuildMenu()
		{
			static HANDLE hPrebuildMenuHook = NULL;

			if( DB::Setting::GetByte( SET_GETCONTACTINFO_ENABLED, DEFVAL_GETCONTACTINFO_ENABLED ) ) 
			{

				if( !hPrebuildMenuHook )
				{
					hPrebuildMenuHook = HookEvent( ME_CLIST_PREBUILDCONTACTMENU, OnPreBuildMenu );
				}

				if( !nhMenuItem ) 
				{
					CLISTMENUITEM mi;

					// insert contact menuitem
					ZeroMemory( &mi, sizeof( mi ) );
					mi.cbSize = sizeof( mi );
					mi.position = -2000010000;
					mi.hIcon = NIcoLib::GetIcon( ICO_BTN_GOTO );
					mi.pszName = "&Homepage";
					mi.pszService = MS_USERINFO_HOMEPAGE_OPENURL;
					nhMenuItem = ( HANDLE )CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi );
				}
			}
			else 
			{
				if( hPrebuildMenuHook ) 
				{
					UnhookEvent( ME_CLIST_PREBUILDCONTACTMENU );
					hPrebuildMenuHook = NULL;
				}
				if( nhMenuItem ) 
				{
					CallService( MS_CLIST_REMOVECONTACTMENUITEM, ( WPARAM )nhMenuItem, NULL );
					nhMenuItem = NULL;
				}
			}
		}

		/**
		 * Force all icons to be reloaded.
		 *
		 * @param	wParam	- handle to the contact whose extra icon is to apply
		 * @param lParam	- not used
		 **/
		VOID ApplyCListIcons()
		{
			HANDLE hContact;

			//walk through all the contacts stored in the DB
			for( hContact = DB::Contact::FindFirst();	hContact != NULL;	hContact = DB::Contact::FindNext( hContact ) )
			{
				OnCListApplyIcons( ( WPARAM ) hContact, 0 );
			}
		}

		/**
		 * Enable or disable the replacement of clist extra icons.
		 *
		 * @param	bEnable		- determines whether icons are enabled or not
		 * @param bUpdateDB	- if true the database setting is updated, too.
		 **/
		VOID EnableExtraIcons( BOOLEAN bEnable, BOOLEAN bUpdateDB ) 
		{
			if( myGlobals.HaveCListExtraIcons )
			{
				static HANDLE	hChangedHook			= NULL;
				static HANDLE	hApplyIconHook		= NULL;
				static HANDLE	hRebuildIconsHook = NULL;

				if( bUpdateDB )
				{
					DB::Setting::WriteByte( SET_CLIST_EXTRAICON_HOMEPAGE, bEnable );
				}

				if( bEnable ) 
				{
					// hook events
					if( hChangedHook == NULL ) 
					{
						hChangedHook = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged );
					}
					if( hApplyIconHook == NULL ) 
					{
						hApplyIconHook = HookEvent( ME_CLIST_EXTRA_IMAGE_APPLY, OnCListApplyIcons );
					}
					if( hRebuildIconsHook == NULL ) 
					{
						hRebuildIconsHook = HookEvent( ME_CLIST_EXTRA_LIST_REBUILD, OnCListRebuildIcons );
						OnCListRebuildIcons( 0, 0 );
					}
				}
				else 
				{
					UnhookEvent( hChangedHook ); 
					hChangedHook = NULL;
					
					UnhookEvent( hApplyIconHook ); 
					hApplyIconHook = NULL;
					
					UnhookEvent( hRebuildIconsHook ); 
					hRebuildIconsHook = NULL;
				}
				ApplyCListIcons();
			}
		}

		/**
		 * This function initially loads the module uppon startup.
		 **/
		VOID LoadModule()
		{
			CreateServiceFunction( MS_USERINFO_HOMEPAGE_OPENURL, MenuCommand );
			EnableExtraIcons( DB::Setting::GetByte( SET_CLIST_EXTRAICON_HOMEPAGE, DEFVAL_CLIST_EXTRAICON_HOMEPAGE ), FALSE );
		}

	} /* namespace ViewHomepage */

} /* namespace NServices */
